package dao

import (
	"context"
	"errors"
	"github.com/qiniu/qmgo"
	"github.com/sirupsen/logrus"
	"go.mongodb.org/mongo-driver/bson"
	"go.mongodb.org/mongo-driver/mongo"
	"monoblog/config"
	"monoblog/domain/model"
	"monoblog/util"
	"strconv"
	"sync"
)

var (
	articleDirRepo *ArticleDirRepository // 单例实例存储变量
	once8          sync.Once             // 确保初始化只执行一次的同步工具
)

// 初始化 QMGO 集合（单例模式）
func NewArticleDirRepository() *ArticleDirRepository {
	once8.Do(func() { // 并发安全的初始化逻辑，只会执行一次
		articleDirRepo = &ArticleDirRepository{
			collection: config.GetDataBase().Collection(model.ArticleDirCollectionName), //指定集合名称
			ctx:        context.Background(),
		}
	})
	return articleDirRepo // 返回唯一实例
}

type ArticleDirRepository struct {
	collection *qmgo.Collection // QMGO 集合对象（替代原生 mongo.Collection）
	ctx        context.Context  // 上下文（用于数据库操作超时控制）
}

// Add - 新增目录夹 (对应 MongoDB InsertOne)
func (impl *ArticleDirRepository) Add(articleDir *model.ArticleDir) error {
	// 取自增ID
	id, _ := NewAutoIDSequenceDao().NextID(model.ArticleDirCollectionName)
	articleDir.ID = id

	_, err := impl.collection.InsertOne(impl.ctx, articleDir)
	return err
}

// UpdateByID - 按 ID 更新目录夹
func (impl *ArticleDirRepository) UpdateByID(id int64, articleDir model.ArticleDir) error {
	update := util.ObjToUpdateMap(articleDir)
	if len(update) == 0 {
		return nil
	}

	updateDoc := bson.M{"$set": update}

	// 修复：捕获 UpdateOne 返回的错误
	err := impl.collection.UpdateId(impl.ctx, id, updateDoc)
	if errors.Is(err, mongo.ErrNoDocuments) {
		logrus.Warnf("record not found. dont update. id: %v", id)
		return nil
	}
	return err // 正确返回更新操作的错误
}

// DeleteByID - 按 ID 删除目录夹
func (impl *ArticleDirRepository) DeleteByID(id int64) error {
	// 执行删除操作
	err := impl.collection.RemoveId(impl.ctx, id)
	if errors.Is(err, mongo.ErrNoDocuments) {
		logrus.Warnf("record not found. dont delete. id: %v", id)
		return nil
	}
	return err
}

// FindByID 根据ID查询目录夹
func (impl *ArticleDirRepository) FindByID(id int64) (*model.ArticleDir, error) {
	var articleDir model.ArticleDir

	err := impl.collection.Find(impl.ctx, qmgo.M{"_id": id}).One(&articleDir)

	if errors.Is(err, mongo.ErrNoDocuments) {
		logrus.Warnf("record not found. id: %v", id)
		return nil, errors.New("找不到数据, id: " + strconv.FormatInt(id, 10))
	}
	return &articleDir, err
}

// FindListByUserId 查询用户下的目录夹list
func (impl *ArticleDirRepository) FindListByUserId(userId string) ([]*model.ArticleDir, int, error) {
	var dirs = make([]*model.ArticleDir, 0)

	// 构建查询条件：根据userId查询
	filter := bson.M{"userId": userId}

	err := impl.collection.Find(impl.ctx, filter).Sort("seq").All(&dirs)
	return dirs, len(dirs), err
}

// ExistsByName 根据名称查询目录夹是否存在（因为目录夹名称只在userId下是唯一的）
func (impl *ArticleDirRepository) ExistsByName(ignoreID int64, name string, userId string) (bool, error) {
	if name == "" {
		return false, nil
	}
	// 构建查询条件
	filter := bson.M{"name": name, "userId": userId}

	if ignoreID > 0 {
		filter["_id"] = bson.M{"$ne": ignoreID}
	}

	n, err := impl.collection.Find(impl.ctx, filter).Count()
	return n > 0, err
}
